from django.http import HttpResponse, Http404, HttpResponseRedirect
from django.template import loader
from django.shortcuts import render, get_object_or_404
from django.urls import reverse
from django.contrib import messages
from django.contrib.auth import authenticate

from .models import *
from .util import *
from django.views.generic import ListView
from django.db import transaction
from django.utils import timezone


class ContactListView(ListView):
    paginate_by = 10


def index(request):
    if request.user.is_authenticated:
        st = Statistics.objects.all()
        raw_objs = RawMaterial.objects.all()
        product_objs = Product.objects.all()
        context = {
            'statistic_list': st,
            'obj_list': [raw_objs, product_objs]
        }
        return render(request, 'repo/index.html', context)
    else:
        return render(request, 'registration/login.html', {})


from django.core.paginator import Paginator


def generate_delete_record_info(names: [()], user: str):
    if names.__len__ == 0:
        return ''
    cat = ''
    for n in names[:2]:
        cat += f'{n[0]}(尺寸：{n[1]}, 颜色： {n[2]}) '
    base = f'{timezone.now().__str__()}: {user} 删除了{cat}'
    if len(names) <= 2:
        return base
    else:
        return base + '等多个条目'


def generate_new_record_info(names: [()], user: str):
    if names.__len__ == 0:
        return ''
    cat = ''
    for n in names[:2]:
        cat += f'{n[0]}(尺寸：{n[1]}, 颜色： {n[2]}, 数量：{n[3]}) '
    base = f'{timezone.now().__str__()}: {user} 新增了{cat}'
    if len(names) <= 2:
        return base
    else:
        return base + '等多个条目'


def generate_in_record_info(n: (), user: str):
    if n.__len__ == 0:
        return ''
    cat = f'{n[0]}(尺寸：{n[1]}, 颜色： {n[2]})'
    base = f'{timezone.now().__str__()}: {user} 入库：{cat}, 数量：{n[3]}'
    return base


def generate_out_record_info(n: (), user: str):
    if n.__len__ == 0:
        return ''
    cat = f'{n[0]}(尺寸：{n[1]}, 颜色： {n[2]})'
    base = f'{timezone.now().__str__()}: {user} 出库：{cat}, 数量：{n[3]}'
    return base


@transaction.atomic
def common_in(
        request,
        new_func,
        obj: Good,
        tag: str,
        tag_cn: str,
        url_name: str,
        url_full_tag: str
):
    err_msg = ''
    search = None

    page_number = 1
    if request.method == 'POST':
        if request.POST.get('remark-modify', default=None):
            remarks = str(request.POST.get('remark-modify'))
            modify_id = int(request.POST.get('id-remark'))
            modify_obj = obj.objects.filter(id=modify_id).first()
            if modify_obj is not None:
                modify_obj.remarks = remarks
                modify_obj.save()
        elif request.POST.get('delete-multi', default=None):
            multi = str(request.POST.get('delete-multi')).split(',')
            delete_objs = []
            user = ''
            for m in multi:
                if m != '':
                    user = request.POST['user']
                    passwd = request.POST['password']
                    user = authenticate(username=user, password=passwd)
                    if user is not None:
                        delete_id = int(m)
                        good = obj.objects.filter(
                            id=delete_id
                        ).first()
                        if good is None:
                            err_msg = '条目不存在!'
                        else:
                            delete_objs.append((good.name, good.spec, good.color))

                            good.delete()
                            if obj.objects.filter(name=good.name).first() is None:
                                statistics = Statistics.objects.filter(name=good.name).first()
                                if statistics is not None:
                                    statistics.delete()

                    else:
                        err_msg = '密码错误'

            if len(delete_objs) > 0:
                info = generate_delete_record_info(delete_objs, user)
                rcd_ins = CommonRecord()
                rcd_ins.operator = user
                rcd_ins.opera_type = CommonRecord.DELETE
                rcd_ins.info = info
                rcd_ins.save()

        elif request.POST.get('id-delete', default=None):
            user = request.POST['user']
            passwd = request.POST['password']
            user = authenticate(username=user, password=passwd)
            if user is not None:
                delete_id = request.POST['id-delete']
                good = obj.objects.filter(
                    id=delete_id
                ).first()
                if good is None:
                    err_msg = '条目不存在!'
                else:
                    info = generate_delete_record_info([(good.name, good.spec, good.color)], user)
                    rcd_ins = CommonRecord(good_name=good.name, operator=user,
                                           opera_type=CommonRecord.DELETE, info=info)
                    rcd_ins.save()
                    good.delete()
                    if obj.objects.filter(name=good.name).first() is None:
                        statistics = Statistics.objects.filter(name=good.name).first()
                        if statistics is not None:
                            statistics.delete()

            else:
                err_msg = '密码错误'
        elif request.POST.get('id-out', default=None):
            out_id = request.POST['id-out']
            out_num = int(request.POST['num-out'])
            user = request.POST['user-out']
            good = obj.objects.filter(
                id=out_id
            ).first()
            if good is None:
                err_msg = '条目不存在！'
            elif good.stock < out_num:
                err_msg = '库存不足！'
            else:
                info = generate_out_record_info((good.name, good.spec, good.color, out_num), user)
                rcd_ins = CommonRecord(good_name=good.name, operator=user, count=out_num,
                                       opera_type=CommonRecord.OUT, info=info)
                rcd_ins.save()
                good.stock -= out_num
                good.save()

                statistics = Statistics.objects.filter(name=good.name).first()
                if statistics is None:
                    statistics = Statistics(
                        name=good.name, stock=good.stock, color=good.color
                    )
                statistics.stock = good.stock
                statistics.save()

        elif request.POST.get('obj-new', default=None):
            new_obj = request.POST['obj-new']
            new_spec = request.POST['spec-new']
            num_new = request.POST['num-new']
            color_new = request.POST['color-new']
            remark_new = request.POST['remark-new']
            user = request.POST['user-new']
            good = obj.objects.filter(
                name=new_obj, spec=new_spec, color=color_new
            ).first()
            if good is not None:
                err_msg = '该条目已存在！'
            else:
                new_func(new_obj, new_spec, num_new, color_new, remark_new)
                info = generate_new_record_info([(new_obj, new_spec, color_new, num_new)], user)
                rcd_ins = CommonRecord(good_name=new_obj, operator=user, count=num_new,
                                       opera_type=CommonRecord.NEW, info=info)
                rcd_ins.save()

                statistics = Statistics.objects.filter(name=new_obj).first()
                if statistics is None:
                    statistics = Statistics(
                        name=new_obj, stock=num_new

                    )
                    statistics.save()
        else:
            good = request.POST['obj-sel']
            spec = request.POST['spec-sel']
            number = int(request.POST['num-sel'])
            color_value = request.POST['color-sel']
            user = request.POST['user-in']

            good_obj = obj.objects.filter(name=good, spec=spec, color=color_value).first()
            if good_obj is None:
                raise Http404("No object found for good = %s, spec = %s, color = %s" % (good, spec, color_value))
            statistics = Statistics.objects.filter(name=good).first()
            if statistics is None:
                statistics = Statistics(
                    name=good, stock=good_obj.stock
                )

            info = generate_in_record_info((good, spec, color_value, number), user)
            rcd_ins = CommonRecord(good_name=good, operator=user, count=number,
                                   opera_type=CommonRecord.IN, info=info)
            rcd_ins.save()
            good_obj.stock += number
            statistics.stock += number
            good_obj.save()
            statistics.save()

    else:
        p = request.GET.get('page')
        if p:
            page_number = int(request.GET.get('page'))
        search = request.GET.get('search')

    good_objs = obj.objects.all()
    objs = []
    if search:
        for g in good_objs:
            lo = str(search).lower()
            if lo in str(g.name).lower() or lo in str(g.spec).lower():
                objs.append(g)
    else:
        objs = good_objs

    paginator = Paginator(objs, 10)
    page_obj = paginator.get_page(page_number)

    prev_page_html = None
    pprev_page_html = None
    next_page_html = None
    nnext_page_html = None

    current_page_html = str.format(
        '<li class="page-item active"><a class="page-link" href="?page=%d">%d</a></li>' % (page_number, page_number))
    if page_obj.has_previous():
        prev_page_html = str.format('<li class="page-item"><a class="page-link" href="?page=%d">%d</a></li>' % (
        page_number - 1, page_number - 1))
        if page_number - 1 > 1:
            pprev_page_html = str.format('<li class="page-item"><a class="page-link" href="?page=%d">%d</a></li>' % (
            page_number - 2, page_number - 2))
    if page_obj.has_next():
        next_page_html = str.format('<li class="page-item"><a class="page-link" href="?page=%d">%d</a></li>' % (
        page_number + 1, page_number + 1))
        if page_number + 1 < paginator.num_pages:
            nnext_page_html = str.format('<li class="page-item"><a class="page-link" href="?page=%d">%d</a></li>' % (
                page_number + 2, page_number + 2))

    spec_dict = {}
    color_dict = {}
    for g in objs:
        if spec_dict.get(g.name) is None:
            spec_dict[g.name] = [g.spec]
            color_dict[g.name + g.spec] = [g.color]
        elif g.spec not in spec_dict[g.name]:
            spec_dict[g.name].append(g.spec)
            color_dict[g.name + g.spec] = [g.color]
        else:
            color_dict[g.name + g.spec].append(g.color)

    context = {
        'obj_spec_dict': spec_dict,
        'obj_color_dict': color_dict,
        'obj_list': page_obj,
        'tag': tag,
        'tag_cn': tag_cn,
        'url_name': url_name,
        'url_full_tag': url_full_tag,
        'err_msg': err_msg,
        'current_page_html': current_page_html,
        'prev_page_html': prev_page_html,
        'pprev_page_html': pprev_page_html,
        'next_page_html': next_page_html,
        'nnext_page_html': nnext_page_html
    }
    return context


def produce(request):
    if request.user.is_authenticated is False:
        return render(request, 'registration/login.html', {})

    def new_product(new_obj, new_spec, new_stock, new_color, new_remark):
        product = Product(name=new_obj, spec=new_spec, stock=new_stock, color=new_color, remarks=new_remark)
        product.save()

    ctx = common_in(
        request,
        new_func=new_product,
        obj=Product,
        tag='product',
        tag_cn='产品',
        url_name='produce',
        url_full_tag="/repo/produce/",
    )
    return render(request, 'base_ext.html', ctx)


def purchase(request):
    if request.user.is_authenticated is False:
        return render(request, 'registration/login.html', {})

    def new_raw(new_obj, new_spec, new_stock, new_color, new_remark):
        product = RawMaterial(name=new_obj, spec=new_spec, stock=new_stock, color=new_color, remarks=new_remark)
        product.save()

    ctx = common_in(
        request,
        new_raw,
        obj=RawMaterial,
        tag='raw',
        tag_cn='材料',
        url_name='purchase',
        url_full_tag="/repo/purchase/",
    )
    return render(request, 'base_ext.html', ctx)


def log(request):
    cmn_records = CommonRecord.objects.all()
    ctx = {
        'url_name': 'log',
        'cmn_record_objs': reversed(cmn_records)
    }
    return render(request, 'log.html', ctx)